/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include "test_hi182x_common.h"

using namespace dev;

namespace drivers {
namespace pcie_nic_card {
namespace hisi {
namespace test {

// ========================= PCIeNicCard设备测试 =========================

TEST_F(Hi182xAbiTest, create_hi182x_card_success) {
    // 目标：验证PCIeNicCard设备创建成功
    auto device_driver = m_devices["PCIeNicCard"];
    ASSERT_TRUE(device_driver != nullptr);

    // 使用构造函数创建设备实例
    auto device = device_driver->ctor(&m_test_service, "hi182x_card");
    ASSERT_TRUE(device != nullptr);
}

TEST_F(Hi182xAbiTest, create_hi182x_card_null_service) {
    // 目标：验证创建设备时传入空服务指针的错误处理
    auto device_driver = m_devices["PCIeNicCard"];
    ASSERT_TRUE(device_driver != nullptr);

    // 测试：传入空服务指针应该返回nullptr
    auto device = device_driver->ctor(nullptr, "hi182x_card");
    EXPECT_EQ(device, nullptr);
}

TEST_F(Hi182xAbiTest, init_hi182x_card_null_params) {
    // 目标：验证使用空参数初始化设备时的错误处理
    auto device_driver = m_devices["PCIeNicCard"];
    ASSERT_TRUE(device_driver != nullptr);

    auto device = device_driver->ctor(&m_test_service, "hi182x_card_null_test");
    ASSERT_TRUE(device != nullptr);

    // 测试：使用空参数初始化应返回错误
    status_t ret = device_driver->init(device, nullptr, nullptr);
    EXPECT_EQ(ret, STATUS_ERROR);
}

TEST_F(Hi182xAbiTest, test_hi182x_card_init) {
    // 目标：验证网卡设备的初始化功能
    auto device_driver = m_devices["PCIeNicCard"];
    ASSERT_TRUE(device_driver != nullptr);

    auto device = static_cast<hi182x_card*>(device_driver->ctor(&m_test_service, "hi182x_card_lifecycle"));
    ASSERT_TRUE(device != nullptr);

    // 设置SystemId配置
    auto config = mc::mutable_dict({
        {"SystemId", 1}
    });
    
    // 执行初始化
    EXPECT_TRUE(device->init(config, mc::dict()));
    
    // 验证SystemId设置成功
    EXPECT_EQ(device->m_system_id, 1);
}

TEST_F(Hi182xAbiTest, test_hi182x_card_start_with_network_ports) {
    // 目标：验证网卡设备与网口、光模块组合的启动和停止功能
    // 场景：网卡->网口->光模块的典型层级结构
    auto device_driver = m_devices["PCIeNicCard"];
    ASSERT_TRUE(device_driver != nullptr);

    // 步骤1：创建并初始化网卡设备
    auto device = static_cast<hi182x_card*>(device_driver->ctor(&m_test_service, "hi182x_card_lifecycle"));
    ASSERT_TRUE(device != nullptr);

    auto config = mc::mutable_dict({
        {"SystemId", 1}
    });
    EXPECT_TRUE(device->init(config, mc::dict()));

    // 步骤2：创建并初始化网口设备
    auto port_driver = m_devices["NicPort"];
    ASSERT_TRUE(port_driver != nullptr);

    auto port_device = static_cast<hi182x_port*>(port_driver->ctor(&m_test_service, "hi182x_port"));
    ASSERT_TRUE(port_device != nullptr);
    auto port_config = mc::mutable_dict({
        {"bmc.dev.NetworkPort", mc::dict{{"PortId", 1}, {"MACAddress", "00:11:22:33:44:55"}}}
    });
    EXPECT_TRUE(port_device->init(port_config, mc::dict()));
    port_device->set_parent(device);  // 设置网口的父设备为网卡

    // 步骤3：创建光模块设备并设置父设备为网口
    auto om_driver = m_devices["OpticalTransceiver"];
    ASSERT_TRUE(om_driver != nullptr);

    auto om_device = static_cast<hi182x_optical_module*>(om_driver->ctor(&m_test_service, "hi182x_om"));
    ASSERT_TRUE(om_device != nullptr);
    om_device->set_parent(port_device);  // 设置光模块的父设备为网口

    // 步骤4：启动和停止网卡设备
    EXPECT_TRUE(device->start());
    EXPECT_TRUE(device->stop());
}

TEST_F(Hi182xAbiTest, hi182x_card_full_lifecycle) {
    // 目标：验证网卡设备的完整生命周期（创建->初始化->配置->启动）
    // 场景：通过ABI接口测试完整的设备层级结构和初始化流程
    auto connector = create_test_connector(1, 1, 1);

    // 步骤1：创建并初始化PCIeNicCard设备
    auto device_driver = m_devices["PCIeNicCard"];
    ASSERT_TRUE(device_driver != nullptr);
    auto card_device =
        static_cast<hi182x_card*>(device_driver->ctor(&m_test_service, "hi182x_card_lifecycle"));
    ASSERT_TRUE(card_device != nullptr);

    // 设置网卡位置信息
    card_device->set_position("1");
    
    // 配置PCIe设备信息
    auto card_csr_object =
        mc::mutable_dict{{"bmc.dev.PcieDevice", mc::dict{{"DeviceName", "test_hi182x_card"}}}};

    // 通过ABI接口初始化网卡设备
    status_t card_init_ret = device_driver->init(card_device, &card_csr_object, &connector);
    EXPECT_EQ(card_init_ret, STATUS_OK);

    // 步骤2：创建并初始化NicPort设备
    auto port_driver = m_devices["NicPort"];
    ASSERT_TRUE(port_driver != nullptr);

    auto port_device =
        static_cast<hi182x_port*>(port_driver->ctor(&m_test_service, "hi182x_port_lifecycle"));
    ASSERT_TRUE(port_device != nullptr);

    // 设置网口位置和父设备关系
    port_device->set_position("1");
    port_device->set_parent(card_device);
    
    // 配置网口信息（PortId=1）
    auto port_csr_object = mc::mutable_dict{{"bmc.dev.NetworkPort", mc::dict{{"PortId", 1}}}};

    // 通过ABI接口初始化网口设备
    status_t port_init_ret = port_driver->init(port_device, &port_csr_object, &connector);
    EXPECT_EQ(port_init_ret, STATUS_OK);

    // 步骤3：创建并初始化OpticalTransceiver设备
    auto om_driver = m_devices["OpticalTransceiver"];
    ASSERT_TRUE(om_driver != nullptr);

    auto om_device = static_cast<hi182x_optical_module*>(
        om_driver->ctor(&m_test_service, "hi182x_optical_module_lifecycle"));
    ASSERT_TRUE(om_device != nullptr);

    // 设置光模块位置和父设备关系
    om_device->set_position("1");
    om_device->set_parent(port_device);
    
    // 配置光模块信息
    auto om_csr_object = mc::mutable_dict{{"bmc.dev.OpticalModule", mc::dict{}}};

    // 通过ABI接口初始化光模块设备
    status_t om_init_ret = om_driver->init(om_device, &om_csr_object, &connector);
    EXPECT_EQ(om_init_ret, STATUS_OK);

    // 步骤4：通过ABI接口启动网卡设备
    status_t card_start_ret = device_driver->start(card_device);
    EXPECT_EQ(card_start_ret, STATUS_OK);
}

// ========================= 网卡工具测试 =========================

TEST_F(Hi182xAbiTest, test_hi182x_card_prase_pci_info) {
    // 目标：验证PCI设备信息解析功能
    // 测试：解析NCSI响应中的VID/DID/SVID/SDID信息
    std::vector<uint8_t> rsp_data = {
        0, 0, // rsp_code (不相关)
        0, 0, // reason_code (不相关)
        0,       // major_ver (不相关)
        0,       // minor_ver (不相关)
        0,       // update_ver (不相关)
        0,       // alpha1 (不相关)
        0, 0, 0, // reserved
        0,       // alpha2 (不相关)
        'N', 'A', 'M', 'E', '_', 'S', 'T', 'R', 'I', 'N', 'G', ' ', // name_string (12字节)
        22, 6, 3, 1, // firmware_ver (4字节) - 16.06.03.01
        2, 37, // pci_did (设备ID)
        25, 229, // pci_vid (厂商ID)
        0, 161, // pci_ssid (子系统设备ID)
        25, 229, // pci_svid (子系统厂商ID)
        255, 255, 255, 255, // manufacturer_id
        0, 0, 0, 0, // check_sum (不相关)
        0, 0, 0, 0  // FCS (不相关)
    };
    std::string rsp_str(rsp_data.begin(), rsp_data.end());
    
    // 打印原始数据用于调试
    std::cout << "原始数据 (hex): ";
    for (size_t i = 0; i < rsp_data.size(); ++i) {
        printf("%02x ", rsp_data[i]);
        if ((i + 1) % 16 == 0) std::cout << std::endl;
    }
    std::cout << std::endl;
    
    // 将响应数据转换为结构体
    auto rsp = reinterpret_cast<get_version_id_rsp*>(const_cast<char*>(rsp_str.data()));

    // 提取并转换PCI ID信息为16进制字符串
    char vid_str[16]  = {0};  // 厂商ID
    char did_str[16]  = {0};  // 设备ID
    char svid_str[16] = {0};  // 子系统厂商ID
    char sdid_str[16] = {0};  // 子系统设备ID

    // 使用大端字节序转换
    snprintf(vid_str, sizeof(vid_str), "0x%04x", SHORT_BY_BIG_ENDIAN(rsp->pci_vid));
    snprintf(did_str, sizeof(did_str), "0x%04x", SHORT_BY_BIG_ENDIAN(rsp->pci_did));
    snprintf(svid_str, sizeof(svid_str), "0x%04x", SHORT_BY_BIG_ENDIAN(rsp->pci_svid));
    snprintf(sdid_str, sizeof(sdid_str), "0x%04x", SHORT_BY_BIG_ENDIAN(rsp->pci_ssid));

    // 验证解析结果（华为网卡的标准ID）
    EXPECT_STREQ(vid_str, "0x19e5");   // 华为厂商ID
    EXPECT_STREQ(did_str, "0x0225");   // Hi182x设备ID
    EXPECT_STREQ(sdid_str, "0x00a1");  // 子系统设备ID
    EXPECT_STREQ(svid_str, "0x19e5");  // 子系统厂商ID
}

TEST_F(Hi182xAbiTest, test_hi182x_card_dcbx_status) {
    // 目标：验证DCBX（数据中心桥接交换）状态解析功能
    // DCBX用于配置优先级、流量控制等QoS参数
    // 构造完整的响应数据，符合 oem_huawei_dcbx_status_rsp_t 结构体定义
    // 注意：OEM_HUAWEI_DCBX_STATUS_RSP_LEN 定义为 48 字节
    std::vector<uint8_t> rsp_data(OEM_HUAWEI_DCBX_STATUS_RSP_LEN, 0);
    
    // public_rsp_header (12 字节)
    rsp_data[0]  = 0;    // response_code (低位)
    rsp_data[1]  = 0;    // response_code (高位)
    rsp_data[2]  = 0;    // reason_code (低位)
    rsp_data[3]  = 0;    // reason_code (高位)
    rsp_data[4]  = 0x00; // manufacturer_id (字节 0)
    rsp_data[5]  = 0x00; // manufacturer_id (字节 1)
    rsp_data[6]  = 0x07; // manufacturer_id (字节 2)
    rsp_data[7]  = 0xDB; // manufacturer_id (字节 3，华为厂商ID)
    rsp_data[8]  = 0;    // reserved
    rsp_data[9]  = 0x01; // oem_command_id
    rsp_data[10] = 0x02; // sub_command_id (OEM_HUAWEI_GET_DCBX_STATUS)
    rsp_data[11] = 0;    // reserved_2
    
    // DCBX 数据字段 (从偏移 12 开始)
    // cos2_up: CoS到用户优先级映射 (8 字节)
    for (int i = 0; i < 8; ++i) {
        rsp_data[12 + i] = static_cast<uint8_t>(i);
    }
    
    // up_pgid: 用户优先级到优先级组映射 (8 字节，全部为0)
    // 已经在初始化时设置为0，无需修改
    
    // pgpct: 优先级组带宽百分比 (8 字节)
    rsp_data[28] = 100; // 第一个优先级组带宽为100%
    
    // strict: 严格优先级模式 (8 字节)
    for (int i = 0; i < 7; ++i) {
        rsp_data[36 + i] = 1; // 前7个为1
    }
    rsp_data[43] = 0; // 最后一个为0
    
    // pfcmap: 基于优先级的流量控制映射 (1 字节)
    rsp_data[44] = 0;
    
    // reserved (3 字节) 和 check_sum (4 字节) 保持为0
    
    // 确保数据大小符合结构体定义
    ASSERT_EQ(rsp_data.size(), OEM_HUAWEI_DCBX_STATUS_RSP_LEN);
    
    std::string rsp_str(rsp_data.begin(), rsp_data.end());
    auto rsp = reinterpret_cast<oem_huawei_dcbx_status_rsp*>(const_cast<char*>(rsp_str.data()));

    // 解析DCBX状态信息
    ncsi_dcbx_status_t dcbx_status = {};
    memcpy(dcbx_status.cos2_up, rsp->cos2_up, MCTP_NCSI_DCBX_FIELD_LEN);      // CoS映射
    memcpy(dcbx_status.up_pgid, rsp->up_pgid, MCTP_NCSI_DCBX_FIELD_LEN);      // 优先级组映射
    memcpy(dcbx_status.pgpct, rsp->pgpct, MCTP_NCSI_DCBX_FIELD_LEN);          // 带宽百分比
    memcpy(dcbx_status.strict, rsp->strict, MCTP_NCSI_DCBX_FIELD_LEN);        // 严格优先级
    dcbx_status.pfcmap = rsp->pfcmap;                                          // 流量控制映射

    // 验证 cos2_up 字段
    EXPECT_EQ(dcbx_status.cos2_up[0], 0);
    EXPECT_EQ(dcbx_status.cos2_up[1], 1);
    EXPECT_EQ(dcbx_status.cos2_up[2], 2);
    EXPECT_EQ(dcbx_status.cos2_up[3], 3);
    EXPECT_EQ(dcbx_status.cos2_up[4], 4);
    EXPECT_EQ(dcbx_status.cos2_up[5], 5);
    EXPECT_EQ(dcbx_status.cos2_up[6], 6);
    EXPECT_EQ(dcbx_status.cos2_up[7], 7);

    // 验证 up_pgid 字段
    EXPECT_EQ(dcbx_status.up_pgid[0], 0);
    EXPECT_EQ(dcbx_status.up_pgid[1], 0);
    EXPECT_EQ(dcbx_status.up_pgid[2], 0);
    EXPECT_EQ(dcbx_status.up_pgid[3], 0);
    EXPECT_EQ(dcbx_status.up_pgid[4], 0);
    EXPECT_EQ(dcbx_status.up_pgid[5], 0);
    EXPECT_EQ(dcbx_status.up_pgid[6], 0);
    EXPECT_EQ(dcbx_status.up_pgid[7], 0);

    // 验证 pgpct 字段
    EXPECT_EQ(dcbx_status.pgpct[0], 100);
    EXPECT_EQ(dcbx_status.pgpct[1], 0);
    EXPECT_EQ(dcbx_status.pgpct[2], 0);
    EXPECT_EQ(dcbx_status.pgpct[3], 0);
    EXPECT_EQ(dcbx_status.pgpct[4], 0);
    EXPECT_EQ(dcbx_status.pgpct[5], 0);
    EXPECT_EQ(dcbx_status.pgpct[6], 0);
    EXPECT_EQ(dcbx_status.pgpct[7], 0);

    // 验证 strict 字段（修正期望值以匹配测试数据）
    EXPECT_EQ(dcbx_status.strict[0], 1);
    EXPECT_EQ(dcbx_status.strict[1], 1);
    EXPECT_EQ(dcbx_status.strict[2], 1);
    EXPECT_EQ(dcbx_status.strict[3], 1);
    EXPECT_EQ(dcbx_status.strict[4], 1);
    EXPECT_EQ(dcbx_status.strict[5], 1);
    EXPECT_EQ(dcbx_status.strict[6], 1);
    EXPECT_EQ(dcbx_status.strict[7], 0);
    
    // 验证 pfcmap 字段
    EXPECT_EQ(dcbx_status.pfcmap, 0);
}

TEST_F(Hi182xAbiTest, test_hi182x_card_get_port_metrics) {
    // 目标：验证网口流量统计信息解析功能
    // 测试：解析RX/TX字节数等统计数据
    std::vector<uint8_t> rsp_data = {
        0, 0, 0, 0, 0, 0, 7, 219, 0, 0, 13, 0, 0, 0, 0, 0,
        0, 18, 136, 216, 0, 0, 0, 0, 0, 18, 108, 212, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 240, 0, 0, 0, 0,
        0, 0, 12, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 8, 241, 0, 0, 0, 0, 0, 0, 11, 250, 0, 0, 0, 0,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 255, 238, 95, 150, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 8, 235, 0, 0, 0, 5, 0, 0, 0, 0,
        0, 0, 12, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 8, 235, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 11, 250,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 18, 136, 216, 0, 0, 0, 0, 0, 0, 0, 0
    };
    std::string rsp_str(rsp_data.begin(), rsp_data.end());
    auto rsp = reinterpret_cast<controller_packet_statistics_rsp*>(const_cast<char*>(rsp_str.data()));

    // 使用网络字节序转换处理64位统计数据
    auto rx_frames = std::to_string(mc::ntoh(rsp->total_bytes_received));      // 接收字节总数
    auto tx_frames = std::to_string(mc::ntoh(rsp->total_bytes_transmitted));   // 发送字节总数

    // 验证解析结果
    EXPECT_EQ(rx_frames, "1214680");  // 约1.2MB接收
    EXPECT_EQ(tx_frames, "1207508");  // 约1.2MB发送
}

} // namespace test
} // namespace hisi
} // namespace pcie_nic_card
} // namespace drivers

